package com.jackwoo.jerrymouse.threads;

import com.jackwoo.jerrymouse.bin.HttpServerScanner;
import com.jackwoo.jerrymouse.bin.Starter;
import com.jackwoo.jerrymouse.bin.SysScanner;
import com.jackwoo.jerrymouse.http.HttpServer;
import com.jackwoo.jerrymouse.http.Request;
import com.jackwoo.jerrymouse.http.Response;
import com.jackwoo.jerrymouse.logger.SocketLogger;
import com.jackwoo.jerrymouse.socket.JerryMouseSocket;
import com.jackwoo.jerrymouse.util.FileUtil;
import com.jackwoo.jerrymouse.util.IOUtil;
import com.jackwoo.jerrymouse.util.SysStaticResGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;

import javax.servlet.http.HttpServlet;
import java.io.*;
import java.net.Socket;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Stream;

/**
 * Author: StupidZhe
 * Date: 2019/11/19
 * Desc: ServerSocket监听线程
 **/
public class ServerSocketThread extends Thread {


    static {
    }

    private Logger logger = LoggerFactory.getLogger(ServerSocketThread.class);

    private ScheduledExecutorService clientThreadPool = Executors.newScheduledThreadPool(100);

    // 监听端口
    private int port;

    // ServerSocket对URL进行解析获得对应HttpServer
    // exp: get /test/index.html 则判断是否test服务
    private Map<String, HttpServer> routerServerMap = new HashMap<>(10);

    private ExecutorService poolExecutor = Executors.newScheduledThreadPool(10);

    public ServerSocketThread(int port) throws IOException {

        // 设置监听端口
        setSocketPort(port);

        // 扫描web-root
        scanWebRoot();
    }


    private void setSocketPort(int port) {
        JerryMouseSocket.PORT = port;
    }

    private void scanWebRoot() throws IOException {
        HttpServerScanner serverScanner = new HttpServerScanner();
        List<String> httpServerList = serverScanner.scan();
        for (String httpServerName : httpServerList) {
//            String router = parseHttpServerName2Router(httpServerName);
            // 生成各个httpServer
            HttpServer httpServer = new HttpServer(httpServerName);
            routerServerMap.put(httpServer.getName(), httpServer);
        }
    }

    @Deprecated
    private String parseHttpServerName2Router(String httpServerName) {
        String[] s = httpServerName.split("[/]");
        return "/" + s[s.length - 1];
    }

    private HttpServer parseRouter(String router) {
        String[] s = router.split("[/]");
        if (s.length < 1) {
            return null;
        }
        return routerServerMap.get(s[1]);
    }

    public void run() {
        JerryMouseSocket jerryMouseSocket = JerryMouseSocket.getInstance();
        while (true) {
            try {

                // 监听
                final Socket client = jerryMouseSocket.accept();

                // 非debug模式下8秒延时等待
                if (!Starter.debugMode) {
                    client.setSoTimeout(8000);
                }
                // 多线程接收clientSocket信息
                Thread clientThread = new Thread(() -> {
                    try {
                        // 获取字节流
//                        List<String> contents = fetchRequestInfo();

                        // 解析字节流生成Request
                        Request request = parseRequest(client.getInputStream());
                        if (request == null) {
                            return;
                        }
                        // 通过http发送命令给jerryMouse
                        parseCommand(request.getRouter());

                        // 获取httpServer
                        HttpServer httpServer = parseRouter(request.getRouter());

                        //
                        if (httpServer == null) {
                            // 返回404页面
                            SysStaticResGenerator.send404(client);
                            closeSocket(client);
                        } else {

                            httpServer.process(request, client);
//                            poolExecutor.execute(new HttpServerThread(client, httpServer, request));
                        }
                    } catch (IOException e) {
                        logger.error("IO ERROR:" + e.getMessage());
                    }
                });

                // 执行socket线程
                // 多线程防止阻塞
                clientThreadPool.execute(clientThread);
                if (Starter.debugMode) {
                    logger.debug("current thread num: " + ((ThreadPoolExecutor) clientThreadPool).getActiveCount());
                }

            } catch (IOException e) {
                SocketLogger.getInstance().error("ServerSocket Listen Error");
            }
        }
    }

    private void parseCommand(String router) {

    }

//    @Deprecated
//    private List<String> fetchRequestInfo(InputStream inputStream) throws IOException {
//        return IOUtil.getLines(inputStream);
//    }

    public Request parseRequest(InputStream requestStream) throws IOException {
        return Request.parseRequest(requestStream);
    }



    private void closeSocket(Socket socket) throws IOException {
        socket.close();
    }
}
